/*--------------------------------------------------------------
 * File: sta.c 编码类型：C语言  UTF-8
 * Author WRS (1352509846@qq.com)
 * 功能: wifi配置为STA模式
 * Version 0.1
 * Date 2024-04-24 
 * 
 * @copyright Copyright (c) 2024
 * 
----------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>
#include <sys/param.h>  // 添加头文件
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "sta.h"
#include "lvgl.h"
#include "ui.h"
#include "lvgl_task.h"
#include "device1.h"
#include "freertos/queue.h"
#include "mqtt_client.h"

extern SemaphoreHandle_t Lvgl_xMutex; // 互斥锁
extern EventGroupHandle_t ui_wifi_event_group;  // ui事件组

static const char *TAG = "WIFI-info";
wifi_config_t wifi_config = 
{
    .sta = {
        .ssid = WIFI_SSID,
        .password = WIFI_PASSWORD,
    },
};
// 创建队列句柄（10条消息深度）
QueueHandle_t mqtt_queue = NULL;
// scan_wifi_t scanWIFInfo = {0};  // 存放扫描出来的wifi信息
wifi_info_t Connect_wifinfo = {0};  // 要连接的wifi信息
static int s_retry_num = 0;
static esp_mqtt_client_handle_t mqtt_client;
mqtt_queue_msg_t msg;
mqtt_queue_msg_t *p_msg = NULL;

// 初始化队列（在app_main中调用）
void mqtt_queue_init(void) 
{
    mqtt_queue = xQueueCreate(10, sizeof(void *));
    if (!mqtt_queue) 
    {
        ESP_LOGE(TAG, "MQTT队列创建失败!");
    }
}

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) 
{
    esp_mqtt_event_handle_t event = event_data;
    switch (event->event_id) {
        case MQTT_EVENT_CONNECTED:  // MQTT连接成功
            ESP_LOGI(TAG, "MQTT Connected");
            // 在这里订阅主题
            esp_mqtt_client_subscribe(mqtt_client, MQTT_SUB_OTA_TOPIC, 1);  // QoS=1
            esp_mqtt_client_subscribe(mqtt_client, MQTT_SUB_INFO_TOPIC, 1);  // QoS=1
            break;
        case MQTT_EVENT_DATA:      // 收到消息
            // 构造队列消息            
            ESP_LOGI(TAG, "Received: Topic=%.*s, Data=%.*s", 
                     event->topic_len, event->topic,
                     event->data_len, event->data);
            // 安全拷贝主题（防止越界）
            size_t topic_len = MIN(event->topic_len, sizeof(msg.topic) - 1);
            strncpy(msg.topic, event->topic, topic_len);
            msg.topic[topic_len] = '\0';

            // 安全拷贝数据（防止越界）
            size_t data_len = MIN(event->data_len, sizeof(msg.data) - 1);
            strncpy(msg.data, event->data, data_len);
            msg.data[data_len] = '\0';
            msg.data_len = data_len;
            p_msg = &msg;
            // 发送到队列（非阻塞方式，队列满时丢弃最旧消息）
            if (xQueueSend(mqtt_queue, &p_msg, 0) != pdTRUE) {
                ESP_LOGW(TAG, "MQTT队列已满,丢弃消息: %s", msg.topic);
            }
            break;
        case MQTT_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "MQTT Disconnected");
            break;
        default:
            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
            break;
    }
}

static void MQTT_init(void)
{
    // 初始化MQTT客户端（新增代码）
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = MQTT_BROKER_ADDR,  // MQTT服务器
        .broker.address.port = MQTT_BROKER_PORT,
        // .credentials.client_id = "esp32_" CONFIG_IDF_TARGET,
    };
    mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(mqtt_client);  // 启动MQTT连接
}

/*--------------------------------------------------------------
 * 功能: wifi连接成功后获取连接到的wifi名称
 * 获取IP地址
 * 订阅MQTT主题
----------------------------------------------------------------*/
static void WIFI_connecet_cb(void)
{
    // 获取默认的STA接口
    esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
    // 获取IPv4地址
    esp_netif_ip_info_t ip_info;
    esp_netif_get_ip_info(netif, &ip_info);
    sprintf(Connect_wifinfo.IP, IPSTR, IP2STR(&ip_info.ip));

    // 获取wifi名称
    wifi_config_t wifi_config;
    esp_wifi_get_config(ESP_IF_WIFI_STA, &wifi_config);
    sprintf(Connect_wifinfo.ssid, "%s", wifi_config.sta.ssid);
    // 打印
    ESP_LOGI(TAG, "wifi: %s IP:" IPSTR, Connect_wifinfo.ssid, IP2STR(&ip_info.ip));
    // 成功获取到IP后 连接MQTT
    MQTT_init();     
}

/*--------------------------------------------------------------
 * 功能: wifi断开后
----------------------------------------------------------------*/
static void WIFI_disconnecet_cb(void)
{
    sprintf(Connect_wifinfo.ssid, "NO Connected");
    while (s_retry_num < 6) // wifi断开后重连6次
    {
        esp_wifi_connect();
        s_retry_num++;
        ESP_LOGI(TAG, "retry to connect to the AP");
        vTaskDelay(pdMS_TO_TICKS(2000));
        // 使用官方API检查连接状态
        wifi_ap_record_t ap_info;
        if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
            ESP_LOGI(TAG, "Reconnected to AP successfully");
            return; // 已连接，退出函数
        }
    }

        // 6次重连失败后关闭Wi-Fi
        ESP_LOGE(TAG, "Failed to reconnect after %d attempts", s_retry_num);
        // 关闭MQTT连接
        if (mqtt_client != NULL) 
        {
            ESP_LOGI(TAG, "Disconnecting MQTT client...");
            esp_mqtt_client_stop(mqtt_client);
        }
    
        // 关闭Wi-Fi以释放资源
        esp_wifi_stop();
        esp_wifi_deinit();
}

static void WIFI_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    switch (event_id)
    {
        // case WIFI_EVENT_STA_CONNECTED: // STA模式连接到AP
        //     {
        //         ESP_LOGI(TAG, "event-->ESP32 station connected to AP");
        //         // WIFI_connecet_cb();
        //         // xEventGroupSetBits(ui_wifi_event_group, WIFI_CONNECTED_BIT);
        //     }break;

        case WIFI_EVENT_STA_DISCONNECTED: // STA模式断开与AP的连接
            {
                ESP_LOGI(TAG, "event-->ESP32 station disconnected from AP");
                xEventGroupSetBits(ui_wifi_event_group, WIFI_DISCONNECTED_BIT);
                if(s_retry_num < 6)
                {
                    WIFI_disconnecet_cb();
                }                                
            }break;

        case IP_EVENT_STA_GOT_IP:
            {
                ESP_LOGI(TAG, "event-->ESP32 station got IP");
                WIFI_connecet_cb();
                xEventGroupSetBits(ui_wifi_event_group, WIFI_GOT_IP_BIT);
            }break;

        default:
            break;
    }
}

void wifi_staMode_init(void)
{
    mqtt_queue_init();
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
    assert(sta_netif);

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&cfg));

    // ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    // ESP_ERROR_CHECK(esp_wifi_start());

    // 注册Wi-Fi事件处理程序
    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &WIFI_event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &WIFI_event_handler, NULL));

    wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
    wifi_config.sta.pmf_cfg.capable = true;
    wifi_config.sta.pmf_cfg.required = false;
    esp_wifi_disconnect();  // 断开连接
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config); // 配置wifi名称和密码
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_LOGI(TAG,"%d\n",esp_wifi_connect()); // 重新连接新的wifi
}

